#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "stdint.h"
#include "stdbool.h"
#include "../lcd_device/include/lcd_device.h"
#include "lcd_gui.h"
#include "font.h"
#include "math.h"  
#include "string.h"
//#include "pic.h"

//π值定义
#define	app_pi	3.1415926535897932384626433832795 

//画点
void lcd_draw_point(unsigned short x, unsigned short y, unsigned short color)
{
	lcd_set_cursor(x,y);//设置光标位置 
	lcd_write_data_16(color); 
}

//画空心圆
void lcd_draw_circle(unsigned short x0,unsigned short y0,unsigned short r,unsigned short color)
{
	int a, b;
	int di;

	a = 0;b = r;di = 3 - (r << 1);             //判断下个点位置的标志

	while(a <= b)
	{
		lcd_draw_point(x0+a,y0-b,color);		//5
 		lcd_draw_point(x0+b,y0-a,color);		//0
		lcd_draw_point(x0+b,y0+a,color);		//4
		lcd_draw_point(x0+a,y0+b,color);		//6
		lcd_draw_point(x0-a,y0+b,color);		//1
 		lcd_draw_point(x0-b,y0+a,color);
		lcd_draw_point(x0-a,y0-b,color);		//2
  		lcd_draw_point(x0-b,y0-a,color);		//7
		a++;
		//使用Bresenham算法画圆
		if(di < 0)
		{
			di += 4*a+6;
		}
		else
		{
			di += 10+4*(a-b);
			b--;
		}
	}
}


// 画实心圆
void lcd_draw_fill_circle(unsigned short x0,unsigned short y0,unsigned short r,unsigned short color)
{
	unsigned short a,b;
	int di;//unsigned short di 画实心菱形

	a = 0;b = r;
	di = 3 - (r << 1);	// 判断下个点位置的标志

	while(a <= b)
	{
		int i = a,p = b;
		while(i>0)
		{
			lcd_draw_point(x0+b,y0-i,color);
			lcd_draw_point(x0-i,y0+b,color);
			i--;
		}
		while(p>0)
		{
			lcd_draw_point(x0-a,y0-p,color);
			lcd_draw_point(x0-p,y0-a,color);
			lcd_draw_point(x0+a,y0-p,color);
			lcd_draw_point(x0-p,y0+a,color);
			lcd_draw_point(x0+a,y0+p,color);
			lcd_draw_point(x0+p,y0+a,color);
			p--;
		}
		a++;
		//Bresenham算法画圆
		if(di<0)
		{
			di += 4*a+6;
		}
		else
		{
			di += 10+4*(a-b);
			b--;
		}
	}

	lcd_draw_point(x0,y0,color); //圆心坐标
}

// 画线(单像素)
void lcd_draw_line(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2,unsigned short color)
{
	unsigned short t; 
	int xerr = 0,yerr = 0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 

	//计算坐标增量 
	delta_x = x2-x1; delta_y = y2-y1; 
	uRow = x1; uCol=y1; 

	if(delta_x > 0)incx = 1; //设置单步方向 
	else if(delta_x == 0)incx = 0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 

	if(delta_y > 0)incy = 1; 
	else if(delta_y == 0)incy = 0;//水平线 
	else{incy = -1;delta_y = -delta_y;} 

	if( delta_x > delta_y)distance = delta_x; //选取基本增量坐标轴 
	else distance = delta_y; 

	for(t = 0;t <= distance+1;t++ )//画线输出
	{
		lcd_draw_point(uRow,uCol,color);//画点 
		xerr += delta_x ; 
		yerr += delta_y ; 

		if(xerr > distance)
		{ 
			xerr -= distance; 
			uRow += incx; 
		} 
		if(yerr > distance)
		{ 
			yerr -= distance; 
			uCol += incy; 
		} 
	}  
}

// 画角度线
void lcd_draw_angle_line(unsigned short x,unsigned short y,unsigned short angle,unsigned short r,unsigned short color)
{
	int sx = x-r;
	int sy = y-r;
	int px0,px1;
	int py0,py1;  
	unsigned char r1; 
	int d = r;

	r1 = d/2 + 3;
	px0 = x;//sx+r+(r-d-7)*sin((app_pi/30)*angle); 
	py0 = y;//sy+r-(r-d-7)*cos((app_pi/30)*angle); 
	px1 = sx+r+r1*sin((app_pi/180)*angle); 
	py1 = sy+r-r1*cos((app_pi/180)*angle); 
	lcd_draw_line(px0,py0,px1,py1,color);
}

//画一条粗线(方法0)
//(x1,y1),(x2,y2):线条的起止坐标
//size：线条的粗细程度
void lcd_draw_bold_line0(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2,unsigned char size,unsigned short color)
{
	unsigned short t; 
	unsigned short xerr=0,yerr=0,delta_x,delta_y,distance; 
	unsigned short incx,incy,uRow,uCol; 

	if(x1<size|| x2<size||y1<size|| y2<size)return;
	delta_x = x2-x1; //计算坐标增量 
	delta_y = y2-y1; 
	uRow = x1; uCol = y1; 

	if(delta_x > 0)incx = 1; //设置单步方向 
	else if(delta_x == 0)incx = 0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 

	if(delta_y > 0)incy = 1; 
	else if(delta_y == 0)incy = 0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 

	if( delta_x > delta_y)distance = delta_x; //选取基本增量坐标轴 
	else distance = delta_y; 

	for(t=0;t <= distance+1;t++ )//画线输出 
	{  
		lcd_draw_fill_circle(uRow,uCol,size,color);//画点 
		xerr += delta_x ; yerr += delta_y ; 

		if(xerr > distance){xerr -= distance;uRow += incx;}  
		if(yerr > distance){yerr -= distance;uCol += incy;}
	}  
} 

//画一条粗线(方法1)
//x0,y0:起点 x1,y1:终点
//size:线粗细,仅支持:0~2.
//color:颜色
void lcd_draw_bold_line1(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned char size,unsigned short color)
{
	int t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 

	delta_x=x1-x0; //计算坐标增量 
	delta_y=y1-y0; 
	uRow=x0; 
	uCol=y0; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 

	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 

	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 

	for(t=0;t<=distance+1;t++ )
	{//画线输出 
		if(size==0)lcd_draw_point(uRow,uCol,color);//画点 
		if(size==1){
			lcd_draw_point(uRow,uCol,color);//画点 
			lcd_draw_point(uRow+1,uCol,color);//画点 
			lcd_draw_point(uRow,uCol+1,color);//画点 
			lcd_draw_point(uRow+1,uCol+1,color);//画点 
		}
		if(size==2){
			lcd_draw_point(uRow,uCol,color);//画点 
			lcd_draw_point(uRow+1,uCol,color);//画点 
			lcd_draw_point(uRow,uCol+1,color);//画点 
			lcd_draw_point(uRow+1,uCol+1,color);//画点 
			lcd_draw_point(uRow-1,uCol+1,color);//画点 
			lcd_draw_point(uRow+1,uCol-1,color);//画点
			lcd_draw_point(uRow-1,uCol-1,color);//画点  
			lcd_draw_point(uRow-1,uCol,color);//画点 
			lcd_draw_point(uRow,uCol-1,color);//画点  
		}
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) { 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) { 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}
}
// 画三角形
void lcd_draw_triangel(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned short color)
{
	lcd_draw_line(x0,y0,x1,y1,color);
	lcd_draw_line(x1,y1,x2,y2,color);
	lcd_draw_line(x2,y2,x0,y0,color);
}

// 画实心三角形
void lcd_draw_fill_triangel(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned short color)
{
	unsigned short a, b, y, last;
	int dx01, dy01, dx02, dy02, dx12, dy12;
	long sa = 0;
	long sb = 0;
	if (y0 > y1) {
		lcd_swap(&y0,&y1); 
		lcd_swap(&x0,&x1);
	}
	if (y1 > y2) {
		lcd_swap(&y2,&y1); 
		lcd_swap(&x2,&x1);
	}
	if (y0 > y1) {
		lcd_swap(&y0,&y1); 
		lcd_swap(&x0,&x1);
	}
	if(y0 == y2) { 
		a = b = x0;
		if(x1 < a){
			a = x1;
		}else if(x1 > b){
			b = x1;
		}

		if(x2 < a){
			a = x2;
		}else if(x2 > b){
			b = x2;
		}
		lcd_draw_fill_rectangle(a,y0,b,y0,color);
		return;
	}
	dx01 = x1 - x0;
	dy01 = y1 - y0;
	dx02 = x2 - x0;
	dy02 = y2 - y0;
	dx12 = x2 - x1;
	dy12 = y2 - y1;
	
	if(y1 == y2)last = y1; 
	else last = y1-1; 

	for(y=y0; y<=last; y++) {
		a = x0 + sa / dy01;
		b = x0 + sb / dy02;
		sa += dx01;
		sb += dx02;
		if(a > b)lcd_swap(&a,&b);

		lcd_draw_fill_rectangle(a,y,b,y,color);
	}
	sa = dx12 * (y - y1);
	sb = dx02 * (y - y0);

	for(; y<=y2; y++) 
	{
		a = x1 + sa / dy12;
		b = x0 + sb / dy02;
		sa += dx12;
		sb += dx02;
		if(a > b)lcd_swap(&a,&b);
		lcd_draw_fill_rectangle(a,y,b,y,color);
	}
}
// 画矩形
void lcd_draw_rectangle(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2,unsigned short color)
{
	lcd_draw_line(x1,y1,x2,y1,color);
	lcd_draw_line(x1,y1,x1,y2,color);
	lcd_draw_line(x1,y2,x2,y2,color);
	lcd_draw_line(x2,y1,x2,y2,color);
}  
// 实心矩形
void lcd_draw_fill_rectangle(unsigned short sx,unsigned short sy,unsigned short ex,unsigned short ey,unsigned short color)
{  	
	unsigned short i,j;			
	unsigned short width = ex-sx+1; 		//得到填充的宽度
	unsigned short height = ey-sy+1;		//高度

	lcd_set_windows(sx,sy,ex,ey);//设置显示窗口

	for(i = 0;i < height;i++)
	{
		for(j = 0;j < width;j++)
		lcd_write_data_16(color);	//写入数据 	 
	}

	lcd_set_windows(0,0,lcd_width-1,lcd_height-1);//恢复窗口设置为全屏
}

// 显示单个字符
void lcd_show_char(unsigned short x,unsigned short y,unsigned short bcolor,unsigned short fcolor, unsigned char ch,unsigned char size,unsigned char mode)
{
	unsigned char temp,pos,t;

	ch=ch-' ';//得到偏移后的值

	lcd_set_windows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口

	if(!mode)   //非叠加方式
	{ 
		for(pos = 0;pos < size;pos++)
		{
			if(size == 12)temp = asc2_1206[ch][pos];//调用1206字体
			else temp = asc2_1608[ch][pos];		 //调用1608字体

			for(t = 0;t < size/2;t++)
			{
				if(temp & 0x01)lcd_write_data_16(fcolor); 
				else lcd_write_data_16(bcolor); 
				temp >>= 1; 
			}
		}
	}
	else   //叠加方式
	{
		for(pos=0;pos<size;pos++)
		{
			if(size == 12)temp = asc2_1206[ch][pos];//调用1206字体
			else temp = asc2_1608[ch][pos];		 //调用1608字体
			for(t = 0;t < size/2;t++)
			{
				if(temp & 0x01)lcd_draw_point(x+t,y+pos,fcolor);//画一个点
				temp >>= 1; 
			}
		}
	}
	lcd_set_windows(0,0,lcd_width-1,lcd_height-1);//恢复窗口为全屏
}

// 显示字符串
void lcd_show_string(unsigned short x,unsigned short y,unsigned short bcolor,unsigned short fcolor,unsigned char size,char *p,unsigned char mode)
{
	while((*p<='~')&&(*p>=' '))   //判断是不是非法字符!
	{
		if(x > (lcd_width-1) || y > (lcd_height-1))return;
		lcd_show_char(x,y,bcolor,fcolor,*p,size,mode);
		x += size/2;p++;
	}
} 

// 显示数字
void lcd_show_num(unsigned short x,unsigned short y,unsigned short bcolor,unsigned short fcolor,unsigned int num,unsigned char len,unsigned char size)
{
	unsigned char t,temp,enshow = 0;

	for(t=0;t<len;t++)
	{
		temp = (num/lcd_pow(10,len-t-1))%10;

		if(enshow == 0 && t < (len-1))
		{
			if(temp == 0)
			{
				lcd_show_char(x+(size/2)*t,y,bcolor,fcolor,' ',size,0);
				continue;
			}else enshow = 1;
		}
	 	lcd_show_char(x+(size/2)*t,y,bcolor,fcolor,temp+'0',size,0);
	}
} 
//显示40*40 QQ图片
void lcd_draw_bmp16(unsigned short x,unsigned short y,const unsigned char *p) 
{
  	int i; 
	unsigned char picH,picL; 

	lcd_set_windows(x,y,x+40-1,y+40-1);//窗口设置

    for(i = 0;i < 40*40;i++)
	{	
	 	picL =* (p+i*2);	//数据低位在前
		picH =* (p+i*2+1);				
		lcd_write_data_16(picH << 8 | picL);  						
	}	
	lcd_set_windows(0,0,lcd_width-1,lcd_height-1);//恢复窗口为全屏
}

unsigned int lcd_pow(unsigned char m,unsigned char n)
{
	unsigned int result = 1;	 
	while(n--)result *= m;    
	return result;
}

void lcd_swap(unsigned short *a, unsigned short *b)
{
	unsigned short tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

